#include "kernel.h"

namespace engine
{

std::list< boost::shared_ptr<Task> > Kernel::active_task_list_;
std::list< boost::shared_ptr<Task> > Kernel::paused_task_list_;

int Kernel::Execute() {
    while(active_task_list_.size()) {        
        boost::shared_ptr<Task> task;

        std::list< boost::shared_ptr<Task> >::iterator i;
        for(i = active_task_list_.begin(); i!=active_task_list_.end(); i++) {       
            task = *i;
            if(!task->GetCanKill())
                task->Update();
        }

        //loop again to remove dead tasks
        active_task_list_.remove_if(CanKillTask);     
    }

    return base::OK_OK;
}

int Kernel::AddTask(boost::shared_ptr<Task> &task) {
    //try to insert the Task in the proper order
    //This will fail if the task is already in the kernel.
    std::list<boost::shared_ptr<Task>>::iterator iterator;

    //First make sure the task isn't hiding in the paused task list.
    iterator = std::find(paused_task_list_.begin(), paused_task_list_.end(), task);
    if(iterator != paused_task_list_.end())
        return engine::ER_DUPLICATE_TASK;
    
    //Now iterate through the task list and try to insert the task
    //This will fail if the task alrady exists
    boost::shared_ptr<Task> temp_task;
    for(iterator = active_task_list_.begin(); iterator != active_task_list_.end(); iterator++) {
        temp_task = *iterator;
        if(temp_task == task)
            return engine::ER_DUPLICATE_TASK;
        else if( CompareTask(temp_task, task) ) 
            break;
    }    

    if(task->Start() == engine::ER_TASK_START_FAIL)
        return engine::ER_TASK_START_FAIL;
     
    active_task_list_.insert(iterator, task);
    return base::OK_OK;
}

int Kernel::SuspendTask(boost::shared_ptr<Task> &task) {
    //first check that this task is in our list 
    //don't want to suspend a task that isn't running    

    //Try to remove the task from the active task list
    std::list<boost::shared_ptr<Task>>::iterator iterator;
    iterator = std::find(active_task_list_.begin(), active_task_list_.end(), task);

    //Assert that the task was removed
    //This can be accomplished by checking that the iterator is not past the end of
    //the active task list.
    bool task_exists = (iterator != active_task_list_.end());

    if(task_exists) {
        //Now its safe to suspend
        if(task->OnSuspend() == engine::ER_TASK_PAUSE_FAIL)
            return engine::ER_TASK_PAUSE_FAIL;

        //remove from the active task pool        
        active_task_list_.erase(iterator);

        //and place the task on in the paused task pool
        paused_task_list_.push_back(task);
        return base::OK_OK;
    }

    return engine::ER_TASK_NOT_FOUND;
}

int Kernel::ResumeTask(boost::shared_ptr<Task> &task) {
    std::list<boost::shared_ptr<Task>>::iterator iterator;    
    iterator = std::find(paused_task_list_.begin(), paused_task_list_.end(), task);
    bool task_exists = iterator != paused_task_list_.end();

    if(task_exists)  {        
        //now we are safe to resume the task
        if(task->OnResume() == engine::ER_TASK_RESUME_FAIL)
            return engine::ER_TASK_RESUME_FAIL;


        //remove it from the paused task pool
        paused_task_list_.erase(iterator);

        //and palce it back in the active task pool
        for(iterator = active_task_list_.begin(); iterator != active_task_list_.end(); iterator++) {
            if( CompareTask(*iterator, task ) )
                break;            
        }
        active_task_list_.insert(iterator, task);
        return base::OK_OK;        
    }

    return engine::ER_TASK_NOT_FOUND;
}

int Kernel::KillTask(boost::shared_ptr<Task> & task) {
    std::list<boost::shared_ptr<Task>>::iterator iterator;

    //Assume the intended task is in the active task pool
    iterator = std::find(active_task_list_.begin(), active_task_list_.end(), task);
    
    if(iterator != active_task_list_.end()) {
        //Found the desired task. lets terminate
        task->SetCanKill(true);
        return base::OK_OK;
    }

    iterator = std::find(paused_task_list_.begin(), paused_task_list_.end(), task);

    if(iterator != paused_task_list_.end()) {
        task->SetCanKill(true);
        return base::OK_OK;
    }

    return engine::ER_TASK_NOT_FOUND;
}

int Kernel::KillAllTasks() {
    std::list<boost::shared_ptr<Task> >::iterator i;
    boost::shared_ptr<Task> task;
    for( i = active_task_list_.begin(); i != active_task_list_.end(); i++) {
        task = *i;
        task->SetCanKill(true);
    }

    return base::OK_OK;
}

int Kernel::ForceShutdown() {
    std::list<boost::shared_ptr<Task> >::iterator i;
    boost::shared_ptr<Task> task;

    int result = 0;
    for( i = active_task_list_.begin(); i != active_task_list_.end(); i++) {
        task = *i;
        result |= task->Stop();
    }

    active_task_list_.clear();
    for( i = paused_task_list_.begin(); i != paused_task_list_.end(); i++) {
        task = *i;
        result |= task->Stop();
    }
    paused_task_list_.clear();

    return result;
}

bool Kernel::CanKillTask(boost::shared_ptr<Task> & task) {
    if(task->GetCanKill()) {
        task->Stop();
        return true;
    }
    
    return false;
}

}